package com.gonsin.gview.logic.services.data;

import com.gonsin.gview.annotations.GContext;
import com.gonsin.gview.annotations.interfaces.ITableDataPicker;
import com.gonsin.base.GPageRequest;
import com.gonsin.gview.logic.exceptions.BaseGViewException;
import com.gonsin.gview.logic.model.DataRequest;
import com.gonsin.gview.logic.utils.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.beanutils.BeanUtilsBean;
import org.springframework.util.NumberUtils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.*;

/**
 * 表格数据处理器
 */
@Slf4j
public class GTableDataPickerManager extends GDataManager{

    private GContext context;

    private String dataId;

    private ITableDataPicker picker;

    private Class searchClass;

    // 每一个成员的属性
    private Map<String, Type> fieldClassMap;

    public GTableDataPickerManager(GContext context, String dataId, ITableDataPicker picker) {
        super(GTableDataPickerManager.class.getName(), picker.getClass().getName());
        this.context = context;
        this.dataId = dataId;
        this.picker = picker;
        Type[] classes = picker.getClass().getGenericInterfaces();
        for(Type t :classes){
            if(t instanceof ParameterizedType){
                ParameterizedType parameterizedType = (ParameterizedType) t;
                Type rawType = parameterizedType.getRawType();
                if(rawType == ITableDataPicker.class){
                    Type returnType = parameterizedType.getActualTypeArguments()[0];
                    searchClass = (Class) parameterizedType.getActualTypeArguments()[1];
                }
            }
        }

        assert searchClass != null;

        fieldClassMap = new HashMap<>();
        Field[] allFields = searchClass.getDeclaredFields();
        for(Field field : allFields){
            fieldClassMap.put(field.getName(), field.getGenericType());
        }
    }

    @Override
    public Object generalData(HttpServletRequest request, HttpServletResponse response, DataRequest dataRequest) {
        Map<String, Object> props = dataRequest.getProps();
        if(dataRequest.getProps() == null){
            props = new HashMap<>();
        }
//        List<KeyValue> kvs = dataRequest.getProps();
//        if(!CollectionUtils.isEmpty(kvs)){
//            kvs.forEach(kv -> {
//                props.put(kv.getKey(), kv.getValue());
//            });
//        }
        Object searchPo = null;
        try {
            searchPo = Class.forName(searchClass.getTypeName()).newInstance();
        } catch (Exception e) {
            log.error(e.toString(), e);
//            throw new ClassNewInstanceException();
            throw new BaseGViewException(String.format("无法创建类【%s】", searchClass.getName()));
        }

//        Enumeration<String> names = request.getParameterNames();
//        Map<String, Object> params = new HashMap<>();
//        while(names.hasMoreElements()){
//            String key = names.nextElement();
//            String value = request.getParameter(key);
//            Class clazz = fieldClassMap.get(key);
//            if(clazz == null){
//                params.put(key, value);
//            } else {
//                if(Integer.class == clazz){
//                    params.put(key, Integer.valueOf(value));
//                } else if(String.class == clazz){
//                    params.put(key, value);
//                } else if(Boolean.class == clazz){
//                    params.put(key, Boolean.valueOf("true".equalsIgnoreCase(value)));
//                } else if(Float.class == clazz){
//                    params.put(key, Float.valueOf(value));
//                } else if(Double.class == clazz){
//                    params.put(key, Double.valueOf(value));
//                } else if(Byte.class == clazz){
//                    params.put(key, Byte.valueOf(value));
//                } else if(Short.class == clazz){
//                    params.put(key, Short.valueOf(value));
//                } else if(Character.class == clazz){
//                    params.put(key, Character.valueOf(value.toCharArray()[0]));
//                } else {
////                    params.put(key, value);
//                }
//            }
//        }

//        List<KeyValue> keyValues = dataRequest.getProps();
        Map<String, Object> params = new HashMap<>();
        for(Map.Entry<String, Object> keyValue : props.entrySet()){
            String key = keyValue.getKey();
            Object value = keyValue.getValue();
            Type clazz = fieldClassMap.get(key);
            if(clazz == null){
                params.put(key, value);
            } else {
                if(clazz.equals(value.getClass())){
                    params.put(key, value);
                } else {
                    try {
                        params.put(key, ValueUtils.parseValue(value, clazz));
                    } catch (Exception ex) {
                        log.warn(ex.toString(), ex);
                        log.warn("设置参数【{}】，设置的内容为“{}“", key, value);
                    }
                    value = null;
                }
            }
        }

        try {
            BeanUtilsBean utils = BeanUtilsBean.getInstance();
            utils.getConvertUtils().register(new MyDateConverter(), java.util.Date.class);
            utils.getConvertUtils().register(new MyBooleanConverter(), Boolean.class);
            utils.getConvertUtils().register(new MyIntegerConverter(), Integer.class);
            utils.getConvertUtils().register(new MyLongConverter(), Long.class);
            utils.getConvertUtils().register(new MyShortConverter(), Short.class);
            utils.getConvertUtils().register(new MyByteConverter(), Byte.class);
            utils.getConvertUtils().register(new MyDoubleConverter(), Double.class);
            utils.getConvertUtils().register(new MyFloatConverter(), Float.class);
            utils.getConvertUtils().register(new MyCharConverter(), Character.class);
            utils.populate(searchPo, params);
        } catch (Exception e) {
            log.error(e.toString() ,e);
            throw new BaseGViewException(String.format("无法创建类【%s】", searchClass.getName()));
        }

        GPageRequest pageRequest = new GPageRequest();
        pageRequest.setPage(NumberUtils.parseNumber(Objects.toString(params.get("page")), Integer.class));
        pageRequest.setCount(NumberUtils.parseNumber(Objects.toString(params.get("count")), Integer.class));
        if(params.containsKey("sort")){
            pageRequest.setSort(Objects.toString(params.get("sort")));
        }

        return picker.getTableData(context, dataId, searchPo, pageRequest, request, props);
    }
}
